﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NhJump.Persistence.Batching;
using NUnit.Framework;
using Rhino.Mocks;

namespace NhJump.Persistence.Tests.Batching
{
    [TestFixture]
    public class DeferredValueFixture
    {
        [Test]
        public void Ctor_SchedulesOperationWithBatcher()
        {
            var mockBatcher = MockRepository.GenerateStub<IBatcher>();
            mockBatcher.Expect(x => x.Add(null, null))
               .IgnoreArguments();

            new DeferredValue<int>(mockBatcher, null);

            mockBatcher.VerifyAllExpectations();
        }

        [Test]
        public void Ctor_DoesNotTriggerCriteriaListImmediately()
        {
            var stubBatcher = MockRepository.GenerateStub<IBatcher>();
            var mockCriteria = MockRepository.GenerateMock<ICriteria>();

            mockCriteria.Expect(x => x.List()).Repeat.Never();

            new DeferredValue<int>(stubBatcher, mockCriteria);

            mockCriteria.VerifyAllExpectations();
        }

        [Test]
        public void Value_UninitializedValue_TriggersBatchExecution()
        {
            var mockBatcher = MockRepository.GenerateMock<IBatcher>();
            var value = new DeferredValue<int>(mockBatcher, null);
            mockBatcher.Expect(x => x.ExecuteAndClear());

            var result = value.Value;

            mockBatcher.VerifyAllExpectations();
        }

        [Test]
        public void Value_InitializedValue_DoesNotTriggerBatchExecution()
        {
            var mockBatcher = MockRepository.GenerateMock<IBatcher>();

            Action<IList> enumerationCallbackAction = null;

            mockBatcher.Expect(x => x.Add(null, null))
                .IgnoreArguments()
                .Do((Action<ICriteria, Action<IList>>)((criteria, action)
                    => { enumerationCallbackAction = action; }));

            var value = new DeferredValue<int>(mockBatcher, null);

            mockBatcher.Expect(x => x.ExecuteAndClear())
                .Repeat.Once()
                .Do((Action)(() => enumerationCallbackAction(new [] {0})));

            var result = value.Value;
            result = value.Value;

            mockBatcher.AssertWasCalled(x => x.ExecuteAndClear());
        }
    }
}
